import tileShow from '@/components/tileShow/tileShow.vue'

/*
  @events
  on-selected 如果开启选择功能,每次选中时触发
  on-click 每次点击单个单元时触发
  on-mouse-xx 各种鼠标事件
*/

export default {
  name: 'tilesMap',
  props: {
    // 容器总宽度,指的是前端显示的宽度,而不是图片的真实尺寸
    width: {
      type: [Number, String],
      default: 256
    },
    // 单图块的宽度,前端显示的宽度,而不是图片的真实尺寸
    itemWidth: {
      type: [Number, String],
      default: 32
    },
    // 单个图块的宽度,真实尺寸
    tileWidth: {
      type: [Number, String],
      default: 32
    },
    // 单个图块的高度,真实尺寸
    tileHeight: {
      type: [Number, String],
      default: 32
    },
    // 显示的图块集
    tiles: {
      type: Array,
      default () {
        return []
      }
    },
    // 在通过src显示图块的前提下,图块的额外样式
    imageExtraStyle: {
      type: Object,
      default () {
        return {}
      }
    },
    // 是否显示固定边框
    borderEnabled: {
      type: Boolean,
      default: false
    },
    // 是否开启hover模式
    hoverBorderEnabled: {
      type: Boolean,
      default: false
    },
    // 选择模式: drag 拖拽选择, click 点击选择, 其他值 不开启选择功能
    selectedMode: {
      type: String,
      default: ''
    }
  },
  components: {
    tileShow
  },
  data () {
    return {
      // 样式
      imagesStyle: {
        width: this.width + 'px'
      },
      imageStyle: {
        width: this.itemWidth + 'px',
        height: (parseInt(this.itemWidth) * (parseInt(this.tileHeight) / parseInt(this.tileWidth))) + 'px'
      },
      
      // 拖拽标记
      isDragSignal: false,
      // 拖拽选中的范围
      dragRange: null,
      // 拖拽缓存
      dragRememberIndex: -1,
      // 当前点击的index
      clickIndex: null,
    }
  },
  computed: {    
    // 选中图片样式
    selectedStyle () {
      return (index) => {
        if (this.selectedMode === 'click' && this.clickIndex === index) {
          // 点击模式
          return {
            border: '2px solid black'
          }
        }
        else if (this.selectedMode === 'drag') {
          // 拖拽模式
          if (!this.dragRange) {
            return {}
          }
          
          let result = {}
          const indexMap = this.solveIndex(index)
          const range = this.solveDragRange()
          if (indexMap.colIndex === range.colIndexStart
            && indexMap.rowIndex >= range.rowIndexStart
            && indexMap.rowIndex <= range.rowIndexEnd) {
            result.borderLeft = '2px solid black'
          }
          if (indexMap.colIndex === range.colIndexEnd
            && indexMap.rowIndex >= range.rowIndexStart
            && indexMap.rowIndex <= range.rowIndexEnd) {
            result.borderRight = '2px solid black'
          }
          if (indexMap.rowIndex === range.rowIndexStart
            && indexMap.colIndex >= range.colIndexStart
            && indexMap.colIndex <= range.colIndexEnd) {
            result.borderTop = '2px solid black'
          }
          if (indexMap.rowIndex === range.rowIndexEnd
            && indexMap.colIndex >= range.colIndexStart
            && indexMap.colIndex <= range.colIndexEnd) {
            result.borderBottom = '2px solid black'
          }
                    
          return result        
        }
        return {}
      }
    },
    
    // 固定边框显示情况
    borders () {
      return (index) => {
        if (this.borderEnabled) {
          // 默认所有格子都有上边框和右边框
          let result = [false, true, true, false]
          const colNum = Math.floor(this.width / this.itemWidth)
          const rowNum = Math.ceil(this.tiles.length / colNum)
          // 首列拥有左边框
          if (index % colNum === 0) {
            result[0] = true
          }
          // 尾行拥有下边框
          if (Math.floor(index / colNum) === rowNum - 1) {
            result[3] = true
          }
          return result          
        }
        return [false, false, false, false]
      }
    },
    
    // 单元图片src绑定
    tileSrc () {
      return (tile) => {
        if (!tile.src) {
          return null
        }
        return tile.src
      }
    }
  },
  methods: {
    // 给定索引,算出行列数
    solveIndex (index) {
      // 用容器视觉宽度除以单元视觉宽度算出列数
      const colNum = Math.floor(this.width / this.itemWidth)
      const rowIndex = Math.floor(index / colNum)
      const colIndex = index % colNum
      
      return { rowIndex, colIndex, colNum }
    },

    // 调整起点和终点的顺序
    solveDragRange () {
      let result = {}
      result.colIndexStart = this.dragRange.dragStartColIndex < this.dragRange.dragEndColIndex ?
        this.dragRange.dragStartColIndex : this.dragRange.dragEndColIndex
      result.colIndexEnd = this.dragRange.dragStartColIndex < this.dragRange.dragEndColIndex ?
        this.dragRange.dragEndColIndex : this.dragRange.dragStartColIndex
      result.rowIndexStart = this.dragRange.dragStartRowIndex < this.dragRange.dragEndRowIndex ?
        this.dragRange.dragStartRowIndex : this.dragRange.dragEndRowIndex
      result.rowIndexEnd = this.dragRange.dragStartRowIndex < this.dragRange.dragEndRowIndex ?
        this.dragRange.dragEndRowIndex : this.dragRange.dragStartRowIndex      
      return result
    },
    
    // 点击触发,用于selectedMode为click时
    clickHandler (index) {
      if (this.selectedMode === 'click') {
        this.clickIndex = index
        this.onObjectSelected()
      }
      this.$emit('on-click', index, this.tiles[index])
    },
    
    // 监听键盘按键
    keydownHandler (index) {
      this.$emit('on-key-down', index, this.tiles[index])
    },
    
    // 监听Ctrl+C
    copyHandler (index) {
      this.$emit('on-copy', index, this.tiles[index])
    },
    
    // 监听Ctrl+V
    pasteHandler (index) {
      this.$emit('on-paste', index, this.tiles[index])
    },
    
    // 开始选取拖拽范围
    mousedownHandler (index) {
      if (this.selectedMode === 'drag') {
        this.isDragSignal = true
        if (!this.dragRange) {
          this.dragRange = {}
        }
        let indexMap = this.solveIndex(index)
        this.$set(this.dragRange, 'dragStartRowIndex', indexMap.rowIndex)
        this.$set(this.dragRange, 'dragStartColIndex', indexMap.colIndex)
        this.$set(this.dragRange, 'dragEndRowIndex', indexMap.rowIndex)
        this.$set(this.dragRange, 'dragEndColIndex', indexMap.colIndex)
      }
      this.$emit('on-mouse-down', index, this.tiles[index])
    },
    
    // 结束选取拖拽范围
    mouseupHandler (index) {
      if (this.selectedMode === 'drag') {
        this.isDragSignal = false
        // 选取结束,触发回调
        this.onObjectSelected()
      }
      this.$emit('on-mouse-up', index, this.tiles[index])
    },
    
    // 拖拽中
    mouseenterHandler (index) {
      if (this.selectedMode === 'drag' && this.isDragSignal) {
        let indexMap = this.solveIndex(index)
        
        this.$set(this.dragRange, 'dragEndRowIndex', indexMap.rowIndex)
        this.$set(this.dragRange, 'dragEndColIndex', indexMap.colIndex)
      }
      this.$emit('on-mouse-enter', index, this.tiles[index])
    },
    
    // 选中范围触发
    onObjectSelected () {
      let data = this.getSelectedObject()
      this.$emit('on-selected', data)
    },
    
    // 获取选中单位
    getSelectedObject () {
      let result = {}
      // 记录宽高一定要记录容器宽高,而不是视觉宽高
      result.itemWidth = this.tileWidth
      result.itemHeight = this.tileHeight
      // 处理范围选取
      if (this.selectedMode === 'drag') {
        // 用容器视觉宽度除以单元视觉宽度算出列数
        const colNum = Math.floor(this.width / this.itemWidth)
        // 划分范围
        const range = this.solveDragRange()
        result.rowIndexStart = range.rowIndexStart
        result.rowIndexEnd = range.rowIndexEnd
        result.colIndexStart = range.colIndexStart
        result.colIndexEnd = range.colIndexEnd
        result.colNum = (range.colIndexEnd - range.colIndexStart) + 1
        result.rowNum = (range.rowIndexEnd - range.rowIndexStart) + 1
        // 获取具体的对象
        result.items = []
        for (let i = range.rowIndexStart; i <= range.rowIndexEnd; i++) {
          for (let j = range.colIndexStart; j <= range.colIndexEnd; j++) {
            const index = i * colNum + j
            let obj = this.tiles[index]
            // 删掉objectsIndex这个临时用的键值
            delete obj.objectsIndex
            result.items.push(obj)
          }
        }
      }
      if (this.selectedMode === 'click') {
        // 划分范围
        let indexMap = this.solveIndex(this.clickIndex)
        result.rowIndexStart = indexMap.rowIndex
        result.rowIndexEnd = indexMap.rowIndex
        result.colIndexStart = indexMap.colIndex
        result.colIndexEnd = indexMap.colIndex
        result.colNum = 1
        result.rowNum = 1
        // 获取具体对象
        let obj = this.tiles[this.clickIndex]
        delete obj.objectsIndex
        result.items = [obj]
        // Autotile特殊标记
        if (obj.type === 'Autotile') {
          result.isAutotile = true
        }
      }
      
      return result
    },
    
    // 清楚选中内容
    clearSelected () {
      this.dragRange = null
      this.clickIndex = null
    }
  },
}